Skip to content

fix(router): preserve Windows literal path payloads through skill dispatch#481

Merged
Q00 merged 1 commit into
Q00:mainfrom
shaun0927:fix/router-preserve-literal-payloads
Apr 29, 2026
Merged

fix(router): preserve Windows literal path payloads through skill dispatch#481
Q00 merged 1 commit into
Q00:mainfrom
shaun0927:fix/router-preserve-literal-payloads

Conversation

@shaun0927
Copy link
Copy Markdown
Collaborator

@shaun0927 shaun0927 commented Apr 22, 2026

Summary

  • preserve Windows drive-letter (C:\…) and UNC (\\server\share\…) literal path payloads through extract_first_argument so backslashes survive skill dispatch
  • add focused regression coverage at the extract_first_argument and end-to-end resolve_skill_dispatch levels

Refs #480.

Problem

extract_first_argument returns single-line remainders through shlex.split, which on POSIX treats backslash as an escape character and silently drops it. So Windows literal path payloads reach the dispatched MCP tool stripped of every backslash:

Input remainder shlex.split (POSIX) result rejoined
C:\temp\seed.yaml --strict C:tempseed.yaml --strict
\\server\share\seed.yaml --strict servershareseed.yaml --strict

That contradicts the documented seed_file_or_content contract for /ouroboros:run and breaks any other skill argument that legitimately contains backslashes on Windows callers.

What changed

src/ouroboros/router/dispatch.py

  • new module-level pattern _WINDOWS_LITERAL_PATH_PATTERN recognizing the two literal-path shapes ([A-Za-z]:\ and \\)
  • extract_first_argument carves out a narrow fast path after the existing multiline branch: if the trimmed remainder starts with one of those prefixes, return the verbatim remainder and skip shell tokenization entirely
  • the Windows-literal classification runs against remainder.strip() while the return value is the unstripped remainder, so any incidental leading whitespace in the original payload is preserved

The router parser layer is unchanged; this is strictly a extract_first_argument carve-out.

Tests

  • tests/unit/router/test_extract_first_argument.py
    • drive-letter path preserved
    • UNC path preserved
    • drive-letter path with incidental leading whitespace preserved
  • tests/unit/router/test_valid_dispatch_normalization.py
    • end-to-end: drive-letter payload reaches mcp_args["seed_path"] and Resolved.first_argument with backslashes intact
    • end-to-end: UNC payload reaches mcp_args["seed_path"] and Resolved.first_argument with backslashes intact

Why this PR is intentionally narrow

The original PR also covered multiline inline seed content, but that scope has since been resolved on main by a separate set of router fixes (bebda68, bb7a456, e8534e0, 40d3cae) using a different implementation strategy. To avoid reintroducing churn or competing designs, this PR has been narrowed to the single concern that main does not yet cover: Windows literal path preservation. The branch was reset on top of main and only the Windows-path fast path remains.

Verification

  • PYTHONPATH=src python3 -m pytest tests/unit/router -q247 passed
  • PYTHONPATH=src python3 -m pytest tests/unit/orchestrator -q804 passed, 1 skipped
  • PYTHONPATH=src python3 -m pytest tests/integration/test_codex_skill_smoke.py tests/integration/test_codex_skill_fallback.py -q3 passed
  • python3 -m ruff check src/ouroboros/router tests/unit/routerAll checks passed

Non-goals

  • changes to multiline inline payload handling (already on main)
  • full native-Windows support beyond the dispatch-payload boundary
  • changes to the documented standalone ouroboros run <seed.yaml> CLI contract
  • changes to natural-language normalization for ordinary single-line skill prompts

Copy link
Copy Markdown
Contributor

@ouroboros-agent ouroboros-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — ouroboros-agent[bot]

Verdict: REQUEST_CHANGES

Reviewing commit b5dcc1a for PR #481

Review record: 10f72bd8-6035-4e4a-9c1c-ab56f2d5dbed

Blocking Findings

| # | File:Line | Severity | Finding |
|### Recovery Notes
First recoverable review artifact generated from codex analysis log.

---|-----------|----------|---------|
| 1 | src/ouroboros/router/dispatch.py:328 | BLOCKING | The new multiline remainder support does not round-trip through the public ParsedOooCommand entrypoint. resolve_skill_dispatch(parsed, ...) and resolve_parsed_skill_dispatch(parsed, prompt=None, ...) reconstruct Resolved.prompt with f"{parsed.command_prefix} {parsed.remainder}", which inserts a space even when the original separator was a newline. For multiline inline seed content, callers that pass a parsed command now get a different prompt than the one they parsed, losing the exact payload layout that this PR is trying to preserve. |

Non-blocking Suggestions

| 1 | tests/unit/router/test_valid_dispatch_normalization.py:151 | tests | Add a regression test that resolves a multiline ParsedOooCommand directly, not just a raw prompt string. That is the public path currently missing coverage, and it would catch the prompt reconstruction issue above. |

Design Notes

The change is narrowly targeted and the parser/extractor split still makes sense, but the new multiline capability is only wired through the raw-prompt flow. The parsed-command API needs the same exact-text preservation guarantee to keep the router’s public contract consistent.


Reviewed by ouroboros-agent[bot] via Codex deep analysis

shaun0927 added a commit to shaun0927/ouroboros that referenced this pull request Apr 29, 2026
The shared router parses ``ParsedOooCommand`` from a raw prompt and exposes a
public API that accepts the parsed object directly. The previous
``_reconstruct_prompt_from_parsed_command`` helper always rejoined the
command prefix and remainder with a single space, which silently collapsed
multiline ``/ouroboros:run`` payloads and other whitespace-sensitive inputs
when callers used the parsed-command entrypoint instead of the raw-prompt
entrypoint.

This change carries the original separator on ``ParsedOooCommand`` so prompt
reconstruction roundtrips exactly. The new field is excluded from equality
comparisons (``compare=False``) so existing parser test fixtures that
construct ``ParsedOooCommand`` without a separator continue to compare
correctly against parser output.

- ``router.types.ParsedOooCommand`` gains ``separator: str = " "``
  (``compare=False``)
- ``router.command_parser`` captures the separator named group from the
  shared regex and forwards it to ``ParsedOooCommand``
- ``router.dispatch._reconstruct_prompt_from_parsed_command`` uses the
  carried separator; ``_validate_parsed_command`` checks that ``separator``
  is a string for symmetry with the other field validators
- regression tests
  - parser: separator capture across space, tab, multiline, and trailing
    whitespace inputs, plus default fallback for absent remainder
  - dispatch: parsed-command-path roundtrip for multiline inline seed
    content, Windows literal paths, and externally constructed
    ``ParsedOooCommand`` defaulting to space separator

Addresses the in-PR review feedback on Q00#481 about the parsed-command
public API path losing newline separators when the raw-prompt path was
already preserving them.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@ouroboros-agent ouroboros-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — ouroboros-agent[bot]

Verdict: REQUEST_CHANGES

Reviewing commit 0eb2cc8 for PR #481

Review record: 48214870-28a8-4838-9c92-3eb843325dec

Blocking Findings

| # | File:Line | Severity | Finding |
|### Recovery Notes
First recoverable review artifact generated from codex analysis log.

---|-----------|----------|---------|
| 1 | src/ouroboros/router/dispatch.py:276 | BLOCKING | The new multiline/Windows fast path calls remainder.strip() before returning it, which silently drops leading indentation and trailing newlines from inline payloads. That contradicts the stated goal of preserving /ouroboros:run\n<yaml> content verbatim, and it can corrupt whitespace-sensitive seed/YAML input before $1 substitution. For example, /ouroboros:run\n goal: test\n will be dispatched as goal: test, not the original payload. |

Non-blocking Suggestions

None.

Design Notes

The separator-roundtripping change is directionally correct and keeps the parsed-command API aligned with the raw-prompt path, but the payload-preservation logic should avoid normalizing the payload itself. Preserve the separator separately; do not mutate remainder when deriving first_argument for whitespace-sensitive inputs.


Reviewed by ouroboros-agent[bot] via Codex deep analysis

@shaun0927
Copy link
Copy Markdown
Collaborator Author

shaun0927 commented Apr 29, 2026

Review response

✅ Blocking — FIXED in commit 0eb2cc8

The bot's call is correct. The contract mismatch where the resolve_skill_dispatch(parsed, ...) path lost the newline separator that the raw-prompt path was already preserving has been closed within the same PR scope.

Changes

  • src/ouroboros/router/types.py — added separator: str = " " (compare=False) to ParsedOooCommand. Excluded from equality, so all 25+ existing parser test fixtures keep working unchanged.
  • src/ouroboros/router/command_parser.py — added a (?P<separator>\s+) named group to the shared regex so the original whitespace between prefix and remainder is captured verbatim.
  • src/ouroboros/router/dispatch.py_reconstruct_prompt_from_parsed_command now uses parsed.separator to reassemble multiline payloads exactly. _validate_parsed_command also gets a separator type check (symmetric with the other field validators).

✅ Non-blocking suggestion — ADDRESSED

Three regression tests added to tests/unit/router/test_valid_dispatch_normalization.py that take a ParsedOooCommand directly as input on the dispatch path:

  • test_resolve_parsed_command_preserves_multiline_inline_seed_content
  • test_resolve_parsed_command_preserves_windows_literal_paths
  • test_resolve_parsed_command_with_externally_constructed_default_separator (guarantees the " " default separator fallback when an external caller constructs ParsedOooCommand without one)

Also added a parametrized separator-capture test in tests/unit/router/test_command_parser.py (space/tab/newline/trailing-spaces) plus a default-separator test.

Verification

  • PYTHONPATH=src python3 -m pytest tests/unit/router -q246 passed (previous 238 + 8 new)
  • PYTHONPATH=src python3 -m pytest tests/unit/orchestrator -q777 passed, 1 skipped
  • PYTHONPATH=src python3 -m pytest tests/integration/test_codex_skill_smoke.py tests/integration/test_codex_skill_fallback.py -q3 passed
  • python3 -m ruff check src/ouroboros/router tests/unit/routerAll checks passed
  • mypy is delegated to CI (GitHub Actions)

Side-effect notes

  • Only the Resolved.prompt echo field is affected. The functional payloads (first_argument, mcp_args) were already preserving multiline / Windows literal inputs through this PR's extract_first_argument change. This commit is a narrow follow-up that closes the prompt-reconstruction consistency gap on the parsed-command public API.
  • ParsedOooCommand stays frozen=True, slots=True. With compare=False, serialization and equality are unaffected.

@Q00 Both the BLOCKING finding and the non-blocking suggestion are addressed within this PR's scope — final review whenever you have time 🙏

shaun0927 added a commit to shaun0927/ouroboros that referenced this pull request Apr 29, 2026
…paths

The previous fast-path branches in ``extract_first_argument`` returned
``remainder.strip()`` for both multiline and Windows-literal payloads, which
silently dropped leading indentation and trailing newlines. That contradicts
the goal of preserving inline ``/ouroboros:run\n<yaml>`` content verbatim;
``/ouroboros:run\n  goal: test\n`` would have been dispatched as
``goal: test`` instead of the original payload.

This commit returns the original ``remainder`` value in both fast-path
branches so whitespace-sensitive seed/YAML inputs reach the MCP tool with
their layout intact. Windows-literal detection still tolerates incidental
leading whitespace by matching against ``remainder.strip()`` for
classification while returning the unstripped value, so existing single-line
Windows tests continue to behave identically.

- ``router.dispatch.extract_first_argument`` returns ``remainder`` (not the
  stripped form) for both multiline and Windows-literal payloads
- regression coverage in ``tests/unit/router/test_extract_first_argument.py``
  for leading indentation, trailing newlines, leading + trailing whitespace
  combos, and Windows literal paths with incidental leading whitespace

Addresses the second bot review on PR Q00#481 about payload normalization in
the multiline/Windows fast paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shaun0927
Copy link
Copy Markdown
Collaborator Author

shaun0927 commented Apr 29, 2026

Review response (2nd round)

✅ Blocking — FIXED in commit 5112c52

The bot is right again. The multiline / Windows fast-path branches in extract_first_argument were returning remainder.strip(), which silently dropped leading indentation and trailing newlines. The case /ouroboros:run\n goal: test\n being dispatched as goal: test was actually reproducible.

Changes (src/ouroboros/router/dispatch.py:276-281)

  • multiline branch: detect via "\n" in remainder or "\r" in remainder directly and return the original remainder
  • Windows-literal branch: classify against remainder.strip() to tolerate incidental leading whitespace, but return the original remainder — existing single-line Windows tests still behave identically
  • the empty-payload guard not remainder.strip() is preserved as-is

Regression coverage (tests/unit/router/test_extract_first_argument.py):

  • multiline-yaml-leading-indent-preserved
  • multiline-yaml-trailing-newline-preserved
  • multiline-yaml-both-leading-and-trailing-whitespace-preserved
  • windows-drive-path-leading-whitespace-preserved

Verification

  • PYTHONPATH=src python3 -m pytest tests/unit/router -q250 passed (previous 246 + 4 new)
  • PYTHONPATH=src python3 -m pytest tests/unit/orchestrator -q777 passed, 1 skipped
  • PYTHONPATH=src python3 -m pytest tests/integration/test_codex_skill_smoke.py tests/integration/test_codex_skill_fallback.py -q3 passed
  • python3 -m ruff check src/ouroboros/router tests/unit/routerAll checks passed
  • mypy is delegated to CI (the previous commit 0eb2cc8 was confirmed SUCCESS)

Design note adopted

The bot's principle of "Preserve the separator separately; do not mutate remainder when deriving first_argument" is now cleanly split:

  • the separator is carried independently on ParsedOooCommand.separator (previous commit 0eb2cc8)
  • extract_first_argument does not mutate remainder for whitespace-sensitive payloads (this commit 5112c52)

@Q00 Both bot rounds have been closed with narrow fix commits — final review whenever you have time 🙏

Copy link
Copy Markdown
Contributor

@ouroboros-agent ouroboros-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — ouroboros-agent[bot]

Verdict: REQUEST_CHANGES

Reviewing commit 5112c52 for PR #481

Review record: fb7a93df-e319-479b-b9af-67e67ed18b92

Blocking Findings

| # | File:Line | Severity | Finding |
|### Recovery Notes
First recoverable review artifact generated from codex analysis log.

---|-----------|----------|---------|
| 1 | src/ouroboros/router/command_parser.py:12 | BLOCKING | The new separator capture is greedy, so for multiline payloads that intentionally begin with indentation, that indentation is consumed into separator instead of staying in remainder. Example: parsing "/ouroboros:run\n goal: test\n" yields separator == "\n " and remainder == "goal: test\n", so extract_first_argument(parsed.remainder) silently drops the leading two spaces. Resolved.prompt roundtrips correctly, but the actual dispatched $1 is wrong for whitespace-sensitive payloads like indented YAML. This is an end-to-end data corruption bug on the parsed/raw dispatch path and needs a parser fix plus a regression test that goes through parse_ooo_command into resolve_skill_dispatch. |

Non-blocking Suggestions

None.

Design Notes

The patch is directionally correct: preserving separator state separately is the right shape, and the extract_first_argument fast paths are narrowly targeted. The remaining issue is in the parser boundary, where separator capture currently mutates the semantic payload for indented multiline inputs.


Reviewed by ouroboros-agent[bot] via Codex deep analysis

shaun0927 added a commit to shaun0927/ouroboros that referenced this pull request Apr 29, 2026
…ndent

The shared command-parser regex used a greedy ``\s+`` for the separator
named group with ``re.DOTALL``, which crossed the newline that ended the
command line and consumed the next line's leading indentation. For an
inline ``/ouroboros:run\n  goal: test\n`` payload that produced
``separator == "\n  "`` and ``remainder == "goal: test\n"``, so even
though ``Resolved.prompt`` reconstructed identically through the carried
separator, ``extract_first_argument(parsed.remainder)`` silently dropped
the YAML's leading two-space indent before ``$1`` substitution. The bug
only surfaced when both ends of the parser/dispatch boundary were
exercised together, which is why the round-2 fix in commit 5112c52
looked sufficient in isolation.

This commit narrows the separator pattern to either same-line spaces and
tabs optionally terminated by a single ``\r?\n``, or same-line spaces
and tabs alone. The newline that ends the command line still becomes the
separator, but any leading whitespace on the next line stays attached to
``remainder`` so whitespace-sensitive payloads reach the MCP tool with
their layout intact. All previously asserted separator captures
(single-space, tab, plain newline, trailing-spaces-only) continue to
hold because the new alternation still captures the same canonical
shapes for those inputs.

- ``router.command_parser`` bounds the separator alternation so leading
  indent on the line after the command prefix is never absorbed
- regression for the parser-level shape: indented multiline payload
  preserves both the leading-indent ``remainder`` and the canonical
  ``"\n"`` separator
- regression for the dispatch-level shape (raw-prompt and parsed-command
  entrypoints): ``$1`` and the resolved ``mcp_args`` carry the verbatim
  indented YAML the caller passed in

Addresses the third bot review on PR Q00#481 (commit 5112c52) about the
parser separator capture mutating the semantic payload for indented
multiline inputs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shaun0927
Copy link
Copy Markdown
Collaborator Author

shaun0927 commented Apr 29, 2026

Review response (3rd round)

✅ Blocking — FIXED in commit c44b09a

The bot's analysis is correct. The round-2 fix made extract_first_argument's fast path return the unstripped remainder, but the bug was actually one stage earlier: the parser regex's (?P<separator>\s+) is greedy, and combined with re.DOTALL it absorbs the leading indentation of the next line. For the input /ouroboros:run\n goal: test\n the regex split was separator == "\n ", remainder == "goal: test\n". The Resolved.prompt round-trip looked fine because the carried separator put the two spaces back, but the actual $1 going through extract_first_argument(parsed.remainder) silently lost the two-space indent — an end-to-end data corruption.

Changes (src/ouroboros/router/command_parser.py:12)

The separator alternation is bounded — (?P<separator>[ \t]*\r?\n|[ \t]+):

  • matches either "same-line spaces/tabs optionally terminated by a single \r?\n" or "same-line spaces/tabs alone"
  • the newline that ends the command line is still absorbed into the separator, but leading indentation on the next line is never pulled into the separator
  • every previously asserted separator capture (single-space, tab, plain newline, trailing-spaces-only) still holds in the same canonical shape

Regression coverage

Added in the exact end-to-end shape the bot asked for in rounds 1 and 3 — "end-to-end through parse_ooo_command into resolve_skill_dispatch":

tests/unit/router/test_command_parser.py

  • slash-prefix-multiline-remainder-preserves-leading-indent — parser-level: indented multiline remainder keeps its indent
  • newline-multiline-yaml-with-indented-payload — parser-level: separator capture itself does not steal the indent

tests/unit/router/test_valid_dispatch_normalization.py

  • test_valid_dispatch_preserves_indented_multiline_inline_seed_content — raw-prompt path end-to-end ($1 and mcp_args carry the verbatim indented YAML)
  • test_resolve_parsed_command_preserves_indented_multiline_payloadParsedOooCommand direct-input path end-to-end (asserts both separator capture and remainder preservation)

Verification

  • PYTHONPATH=src python3 -m pytest tests/unit/router -q254 passed (previous 250 + 4 new)
  • PYTHONPATH=src python3 -m pytest tests/unit/orchestrator -q777 passed, 1 skipped
  • PYTHONPATH=src python3 -m pytest tests/integration/test_codex_skill_smoke.py tests/integration/test_codex_skill_fallback.py -q3 passed
  • python3 -m ruff check src/ouroboros/router tests/unit/routerAll checks passed
  • mypy is delegated to CI (GitHub Actions)

Design note

This effectively lifts the bot's round-2 principle — "Preserve the separator separately; do not mutate remainder when deriving first_argument" — one stage further upstream into the parser itself:

  • (round 1, 0eb2cc8) carry separator independently on ParsedOooCommand.separator — prompt reconstruction round-trip
  • (round 2, 5112c52) extract_first_argument does not mutate remainder — dispatch payload preservation
  • (round 3, c44b09a) parser separator capture does not absorb the payload — the separator/payload boundary itself is now drawn precisely

@Q00 All three bot rounds are addressed with narrow fix commits — final review whenever you have time 🙏

Copy link
Copy Markdown
Contributor

@ouroboros-agent ouroboros-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — ouroboros-agent[bot]

Verdict: APPROVE

Reviewing commit c44b09a for PR #481

Review record: 27a0b168-94c4-4c53-861f-ec21b052cb2a

Blocking Findings

No in-scope blocking findings remained after policy filtering.

Non-blocking Suggestions

None.

Design Notes

The parser/dispatch split is still clean, and the fixes are scoped tightly to the roundtrip problem they were meant to solve. The added separator field is a reasonable way to preserve prompt fidelity without entangling extract_first_argument with reconstruction concerns.

Recovery Notes

First recoverable review artifact generated from codex analysis log.


Reviewed by ouroboros-agent[bot] via Codex deep analysis

…patch

`extract_first_argument` falls through to `shlex.split` for any single-line
remainder, which on POSIX treats backslash as an escape character and
silently strips it. As a result, a Windows drive-letter payload like
`C:\temp\seed.yaml --strict` reaches the dispatched MCP tool as
`C:tempseed.yaml --strict`, and a UNC payload like
`\\server\share\seed.yaml --strict` becomes `servershareseed.yaml --strict`.
That contradicts the documented contract for `seed_file_or_content` and
breaks any other skill argument that legitimately contains backslashes on
Windows callers.

This patch carves out one narrow fast path: if the remainder, after
trimming incidental leading whitespace, starts with a drive-letter prefix
(`[A-Za-z]:\`) or a UNC prefix (`\\`), return the remainder verbatim and
skip shell tokenization entirely. The carve-out runs after the existing
multiline branch (`re.search(r"[\r\n].*\S", remainder)`), so multiline
payloads continue to use the multiline path and natural-language
single-line prompts continue to use shell-style quote stripping.

The Windows-literal pattern matches against `remainder.strip()` for
classification while returning the unstripped value, so any incidental
leading whitespace in the original payload is preserved. The router
parser layer is unchanged.

- `router.dispatch._WINDOWS_LITERAL_PATH_PATTERN` (new) recognizes
  drive-letter and UNC prefixes
- `router.dispatch.extract_first_argument` returns the verbatim
  `remainder` for Windows-literal payloads, before falling through to
  `shlex.split`
- regression for `extract_first_argument`: drive-letter, UNC, and
  drive-letter with incidental leading whitespace
- regression for end-to-end dispatch: drive-letter and UNC payloads reach
  `mcp_args["seed_path"]` and `Resolved.first_argument` with backslashes
  intact

Refs Q00#480.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@shaun0927 shaun0927 force-pushed the fix/router-preserve-literal-payloads branch from c44b09a to 657663c Compare April 29, 2026 15:32
@shaun0927 shaun0927 changed the title fix(router): preserve literal multiline and Windows-path dispatch payloads fix(router): preserve Windows literal path payloads through skill dispatch Apr 29, 2026
@shaun0927
Copy link
Copy Markdown
Collaborator Author

PR scope narrowed and rebased on main

While the previous bot rounds were being addressed, four separate router fixes landed on main (bebda68, bb7a456, e8534e0, 40d3cae) which fully resolve the multiline inline payload concern using a different implementation strategy (a hand-written _extract_command_remainder instead of a regex separator group, and no ParsedOooCommand.separator field).

Rather than reintroduce competing designs or churn, this PR has been:

  1. Reset onto upstream/main (force-push, --force-with-lease)
  2. Narrowed to one concern main does not yet cover: Windows literal path preservation in extract_first_argument

What remains in scope (commit 657663c)

  • _WINDOWS_LITERAL_PATH_PATTERN recognizing drive-letter (C:\…) and UNC (\\server\share\…) prefixes
  • extract_first_argument short-circuits before shlex.split for those payloads, returning the verbatim remainder
  • regression coverage at extract_first_argument (3 cases) and end-to-end resolve_skill_dispatch (2 cases)

What was dropped (already covered by main)

  • multiline inline payload preservation in parse_ooo_command / extract_first_argument / _reconstruct_prompt_from_parsed_command
  • ParsedOooCommand.separator field
  • the multiline-related parser regex changes from rounds 1–3

Why the Windows-path concern is real (not theoretical)

>>> import shlex
>>> shlex.split(r'C:\temp\seed.yaml --strict')
['C:tempseed.yaml', '--strict']
>>> shlex.split(r'\\server\share\seed.yaml')
['servershareseed.yaml']

Any Windows caller hitting the deterministic dispatch path with a literal path payload silently loses every backslash before $1 substitution. The new fast path returns the verbatim remainder only for the two literal-path shapes; ordinary single-line natural-language prompts continue through shlex.split exactly as before.

Verification

  • PYTHONPATH=src python3 -m pytest tests/unit/router -q247 passed
  • PYTHONPATH=src python3 -m pytest tests/unit/orchestrator -q804 passed, 1 skipped
  • PYTHONPATH=src python3 -m pytest tests/integration/test_codex_skill_smoke.py tests/integration/test_codex_skill_fallback.py -q3 passed
  • python3 -m ruff check src/ouroboros/router tests/unit/routerAll checks passed

Reviewer notes

  • The earlier review comments (rounds 1–3) refer to commits that are no longer in the branch history. The earlier discussion remains valuable context for the multiline-related design decisions that ultimately landed via the parallel main PRs, but the current head is a single commit on top of main containing only the Windows-path carve-out.
  • Mergeable state should now be MERGEABLE once GitHub re-evaluates against the new head 657663c.

@Q00 The branch is now scoped to a single concern that does not overlap with anything currently on main — final review whenever you have time 🙏

Copy link
Copy Markdown
Contributor

@ouroboros-agent ouroboros-agent Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — ouroboros-agent[bot]

Verdict: APPROVE

Reviewing commit 657663c for PR #481

Review record: 792d612a-c572-469d-8980-466c3a3e6715

Blocking Findings

No in-scope blocking findings remained after policy filtering.

Non-blocking Suggestions

None.

Design Notes

The scope is appropriately narrow: the extract_first_argument fast path in src/ouroboros/router/dispatch.py fixes a real shlex.split corruption case for Windows drive-letter and UNC literals without changing the broader dispatch pipeline, and the added unit/end-to-end coverage in tests/unit/router/test_extract_first_argument.py and tests/unit/router/test_valid_dispatch_normalization.py matches the intended contract. I could not run pytest locally because the environment is missing the pytest module.

Recovery Notes

First recoverable review artifact generated from codex analysis log.


Reviewed by ouroboros-agent[bot] via Codex deep analysis

@Q00 Q00 merged commit 0504e11 into Q00:main Apr 29, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants